/*
 * Copyright (c) 2014, marco.tamburelli@gmail.com
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met: 
 * 
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer. 
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution. 
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.omorphdb.core.io;

import java.io.Closeable;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * It's a tool which should be used in conjunction with a resource. It should be
 * used to take note about the resource limit.<br>
 * <br>
 * 
 * A resource, couldn't have a physical limit, like in case of files something
 * like EOF, however it's required to know where the last appended byte is.
 * 
 * @author Marco Tamburelli
 */
class ResourceLimitProvider implements Closeable
{
	private final File metaDataFile;
	private long resourceLimit;

	ResourceLimitProvider(File resourceFile) throws IOException
	{
		this.metaDataFile = new File(resourceFile.getCanonicalPath() + ".l");
		readAndRemoveMetaFile();
	}

	synchronized long getResourceLimit()
	{
		return resourceLimit;
	}

	/**
	 * shifts the current resource limit of a provided amount, and returns the
	 * resource limit before the current shift.
	 * 
	 * @param shift
	 * @return
	 */
	synchronized long shiftResourceLimit(int shift)
	{
		long tmp = this.resourceLimit;
		this.resourceLimit += shift;

		return tmp;
	}

	private void createMetaFile() throws IOException
	{
		FileOutputStream fou = new FileOutputStream(this.metaDataFile);
		DataOutputStream out = new DataOutputStream(fou);

		out.writeLong(this.resourceLimit);

		out.close();
		fou.close();
	}

	private void readAndRemoveMetaFile() throws IOException
	{
		if (this.metaDataFile.exists() && this.metaDataFile.isFile())
		{
			FileInputStream fin = new FileInputStream(this.metaDataFile);
			DataInputStream in = new DataInputStream(fin);

			try
			{
				this.resourceLimit = in.readLong();
			}
			catch (IOException e)
			{
				throw e;
			}
			finally
			{
				in.close();
				fin.close();

				this.metaDataFile.delete();
			}
		}

		this.resourceLimit = 0;
	}

	@Override
	public void close() throws IOException
	{
		createMetaFile();
	}
}
